﻿using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;
using Microsoft.Practices.Unity.InterceptionExtension;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;

namespace Framework.IOC
{
    /// <summary>
    /// Represents the Service Locator.
    /// </summary>
    public sealed class ServiceLocator
    {
        #region Private Fields
        private static readonly object Lockobj = new object();
        private IDIContainer _container;
        public IDIContainer Container
        {
            get
            {
                if (_container != null) return _container;
                lock (Lockobj)
                {
                    if (_container == null)
                    {
                        _container = new UnityIOCContainer();

                    }
                }
                return _container;
            }
        }
        #endregion

        #region Private Static Fields
        private static readonly ServiceLocator instance = new ServiceLocator();
        private static Action<IDIContainer> registTypes;
        #endregion

        #region Ctor
        private ServiceLocator()
        {
            //instance._container = new UnityIOCContainer();
        }
        #endregion

        #region Public Static Properties

        public static ServiceLocator Instance
        {
            get { return instance; }
        }
        #endregion

        #region Public Static Methods
        public static void RegistAll(string path)
        {
            var filePaths = Directory.GetFiles(path, "*.dll");
            foreach (var assembly in filePaths.Select(Assembly.LoadFrom))
            {
                List<Type> types;
                try
                {
                    types = assembly.GetTypes().Where(s => s.Name.Equals("Startup")).ToList();
                }
                catch
                {
                    continue;
                }

                foreach (var type in types)
                {
                    var obj = type.GetConstructor(Type.EmptyTypes).Invoke(Type.EmptyTypes);
                    var menthod = type.GetMethod("Configuration", Type.EmptyTypes);
                    if (menthod != null)
                    {
                        menthod.Invoke(obj, Type.EmptyTypes);
                    }
                }
            }
        }

        /// <summary>
        /// 全局注册
        /// </summary>
        /// <param name="registTypes"></param>
        public static void Regist(Action<IDIContainer> registTypes)
        {
            if (registTypes != null)
            {
                registTypes(instance.Container);
            }
        }
        #endregion

        #region Public Methods
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T GetService<T>()
        {
            return instance.Container.Resolve<T>();
        }
        #endregion
        public object GetService(Type serviceType)
        {
            return instance._container.GetService(serviceType);
        }
        public void UnityResolver()
        {

        }
    }
}
